package com.gxp.web.controller;

import com.gxp.common.constant.UserConstants;
import com.gxp.common.core.controller.BaseController;
import com.gxp.common.core.domain.AjaxResult;
import com.gxp.common.core.domain.entity.SysRole;
import com.gxp.common.core.domain.entity.SysUser;
import com.gxp.common.core.domain.entity.ZkServiceType;
import com.gxp.common.enums.UserStatus;
import com.gxp.common.utils.IpUtils;
import com.gxp.common.utils.MessageUtils;
import com.gxp.common.utils.ShiroUtils;
import com.gxp.common.utils.StringUtils;
import com.gxp.framework.shiro.audit.AuditService;
import com.gxp.framework.shiro.service.SysPasswordService;
import com.gxp.system.domain.dto.GxpUserDto;
import com.gxp.system.service.ISysConfigService;
import com.gxp.system.service.ISysMenuService;
import com.gxp.system.service.ISysUserService;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Set;
import java.util.stream.Collectors;

@Controller
@RequestMapping("/gxp")
public class SSJLoginController extends BaseController {

    @Autowired
    private ISysConfigService configService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private SysPasswordService passwordService;
    @Autowired
    private ISysMenuService menuService;
    @Autowired
    private AuditService auditService;

    /**
     * 仪器端登录
     */
    @PostMapping("/checklogin.do")
    @ResponseBody
    public AjaxResult login(@Param("username") String username, @Param("password") String password){
        logger.info("SpinStudioJ Login: username = {}", username);
        StringBuilder msgSb = new StringBuilder();
        // 用户名或密码为空 错误
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
            auditService.recordAuditLoginFail("SpinStudioJ Login", username, MessageUtils.message("not.null"));
            return error(msgSb.append("failed to get username or password").toString());
        }
        // 密码如果不在指定范围内 错误
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
            auditService.recordAuditLoginFail("SpinStudioJ Login", username, MessageUtils.message("user.password.not.match"));
            return error(msgSb.append("password size error").toString());
        }

        // 用户名不在指定范围内 错误
        if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
            auditService.recordAuditLoginFail("SpinStudioJ Login", username, MessageUtils.message("user.password.not.match"));
            return error(msgSb.append("username size error").toString());
        }

        // IP黑名单校验
        String blackStr = configService.selectConfigByKey("sys.login.blackIPList");
        if (IpUtils.isMatchedIp(blackStr, ShiroUtils.getIp())) {
            auditService.recordAuditLoginFail("SpinStudioJ Login", username, MessageUtils.message("login.blocked"));
            return error(msgSb.append("ip black").toString());
        }

        // 查询用户信息
        SysUser user = userService.selectUserByLoginName(username);

        //用户不存在
        if (user == null) {
            auditService.recordAuditLoginFail("SpinStudioJ Login", username, MessageUtils.message("user.not.exists"));
            return error(msgSb.append("user is null").toString());
        }

        //用户被删除
        if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
            auditService.recordAuditLoginFail("SpinStudioJ Login", username, MessageUtils.message("user.password.delete"));
            return error(msgSb.append("user has been deleted").toString());
        }

        //用户被停用
        if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
            auditService.recordAuditLoginFail("SpinStudioJ Login", username, MessageUtils.message("user.blocked"));
            return error(msgSb.append("user has been blocked").toString());
        }

        //校验密码
        if(!passwordService.validateForSSJ(user, password)){
            return error(msgSb.append("password error").toString());
        }
        SysRole role = user.getRoles().get(0);
        auditService.recordAuditLoginSuccess("SpinStudioJ Login", username, ShiroUtils.getRoleNames(), MessageUtils.message("user.login.success"));

        //密码校验成功，传回msg信息，包含权限信息
        Set<String> rolePerms = menuService.selectPermsNameByRoleId(role.getRoleId());
        GxpUserDto gxpUserDto = new GxpUserDto();
        gxpUserDto.setUserId(user.getUserId());
        gxpUserDto.setLoginName(user.getLoginName());
        gxpUserDto.setUserName(user.getUserName());
        gxpUserDto.setStatus(user.getStatus());
        gxpUserDto.setRoles(role.getRoleName());
        gxpUserDto.setServiceTypes(user.getSvtypes().stream().map(ZkServiceType::getSvtypeName).collect(Collectors.toList()));
        gxpUserDto.setPermissions(rolePerms.stream().filter(perm -> !perm.startsWith("esign:")).collect(Collectors.toList()));
        gxpUserDto.setEsignPermissions(rolePerms.stream().filter(perm -> perm.startsWith("esign:")).collect(Collectors.toList()));
        logger.info("SpinStudioJ Login: username = {}, role = {}, perms = {}", username, role.getRoleName(), StringUtils.join(rolePerms, "&"));
        return success().put("code", 200).put("data", gxpUserDto);
    }
}
